<script lang="ts">
export default {
  name: "ElsForm"
}
</script>

<script setup lang="ts">
import {
  useSlots,
  watch,
  onMounted,
  unref,
  ref,
  toRef,
  reactive,
  onBeforeUnmount,
} from "vue";
import { ElsElem } from "../ElsElem"
import useFormPluging from "./elementPlus";
import { set, get, unset,difference,clone } from "lodash-es"
import { IElsForm } from "./inter"
import { useDebounceFn } from '@vueuse/core'

// interface Props extends /* @vue-ignore */ IElsForm.Props {
//   modelValue: IElsForm.Props["modelValue"];
//   column: IElsForm.Props["column"];
//   size?: IElsForm.Props["size"];
//   UIPluging?: IElsForm.Props["UIPluging"];
//   autoClean?: IElsForm.Props["autoClean"];
//   params?:Record<string,any>
// }

const emits = defineEmits<{
  (e: "update:modelValue", v: Record<string, any>): void;
  (e: "change", name: string, value: any): void;
}>();

const props = withDefaults(defineProps<IElsForm.Props>(), {
  size: "default",
  autoClean: true,
  modelValue: () => ({}),
  params: () => ({}),
});
//
const slots = useSlots();
//
const formData = ref<Record<string, any>>(clone(unref(props.modelValue || {})));
let updateLock = false;
// 
// 
const emitChange = useDebounceFn((prop: string, val: any) => {
  emits("change", prop, val);
  //
  emits("update:modelValue", clone(unref(formData)));
  if (updateLock === false) {
    updateLock = true;
    setTimeout(() => { updateLock = false }, 2000)
  }
}, 200)
//
onMounted(() => {
  emits("update:modelValue", clone(unref(formData)));
});
//
watch(toRef(props, "modelValue"), (v) => {
  if (updateLock === false && v) {
    formData.value = clone(v)
  }
  if (updateLock === true) {
    updateLock = false;
  }
});
const formProps = reactive<Set<string>>(new Set<string>());
const UIConfig: IElsForm.UIPluginConfig = { formProps, formData, emitChange };
//
const pluging = props.UIPluging || useFormPluging;
//
const formUI = pluging(props, UIConfig, { slots });
// 当 column 变化时，清除掉 已经删除的对应属性值
if (props.autoClean) {
  let formPropsCache: string[] = [];
  onMounted(() => {
    formPropsCache = Array.from(formProps);
  });
  // 避免在全局刷新时大量元素 unmounted 导致重复响应
  onBeforeUnmount(() => {
    formPropsCache = [];
    formProps.clear();
  });
  //
  watch(formProps, (v) => {
    const arr = Array.from(v);
    const da = difference(formPropsCache, arr);
    if (da.length > 0) {
      da.forEach((p) => unset(unref(formData), p));
      formPropsCache = arr;
      emits("update:modelValue", unref(formData));
    }
  });
}
// 提交 调用 validate 方法 并返回处理的值
const submit = (
  format: (k: string, v: any) => [string, any] = (
    k: string,
    v: any
  ) => ([k, v])
) => {
  return new Promise(async (resolve, reject) => {
    try {
      await formUI.validate();
      const res: Record<string, any> = clone(unref(formData));
      for (const k of Array.from(formProps)) {
        const v = get(unref(formData), k);
        const r = format(k, v);
        (r[0] && r[1] == undefined) && unset(res, r[0])
      }
      resolve(res)
    } catch (e) {
      console.error("表单校验失败！====>", e);
      reject(e)
    }

  })

};
//
defineExpose({ ...formUI, formProps, submit });
</script>

<template>
  <div class="els-form">
    <els-elem :elem="formUI.elem" :params="params" :context="formUI.context"></els-elem>
  </div>
</template>